from __future__ import absolute_import
import logging
import datetime
import time
import re
import traceback
import pymysql
import uuid
from obs import ObsClient
from conf.conf import (ObsAK, ObsEndpoint, ObsSK, BucketName, DBName,
                       DBHost, DBPort, DBUser, DBPassword, FileDir)
obs_client = ObsClient(access_key_id=ObsAK,
                       secret_access_key=ObsSK, server=ObsEndpoint)

mysql_db = pymysql.connect(host=DBHost, port=DBPort, user=DBUser, password=DBPassword, database=DBName)

logger = logging.getLogger(__name__)


def check_obs_new_date(db):
    resp = obs_client.listObjects(BucketName)
    original_list = []
    anonymize_list = []
    scene_list = []
    scene_obj = []
    scene_folder = ""
    if resp.status < 300:
        for content in resp.body.contents:
            if not re.search(FileDir, content.key):
                continue
            now = time.localtime()
            now_time = time.strftime("%Y-%m-%d %H:%M:%S", now)
            key = content.key.rsplit('/', 1)
            file_name = key[1]
            uuid_gen = str(uuid.uuid4())
            if file_name == '':
                continue
            m_size = content.size
            cur_regex = "(\d{4}-\d{1,2}-\d{1,2}-\d{1,2}-\d{1,2}-\d{1,2})"
            mtime = re.search(cur_regex, file_name)  # 提取obs文件名中的时间
            mtime = mtime.group(1)
            collect_time = datetime.datetime.strptime(mtime, "%Y-%m-%d-%H-%M-%S")
            storage_type, restoration_status = check_storage_class(content)
            url = 'obs://{}/{}'.format(BucketName, content.key)
            if re.search(r'anonymize', content.key):
                anonymize_obj = [file_name, m_size, storage_type, restoration_status, collect_time, now_time, now_time,
                                 url, BucketName, content.key, 'v1', 0, 0, uuid_gen]
                anonymize_list.append(anonymize_obj)
            elif re.search(r'scene', content.key):
                cur_folder = key[0].rsplit('/', 1)[1]
                if scene_folder == "":
                    scene_folder = cur_folder
                    url = 'obs://{}/{}'.format(BucketName, key[0])
                    scene_obj = [cur_folder, m_size, storage_type, restoration_status, collect_time, now_time, now_time,
                                 url, BucketName, key[0], 'v1', 0, 0]
                    continue
                if scene_folder != cur_folder:
                    scene_list.append(scene_obj)
                    scene_folder = cur_folder
                    url = 'obs://{}/{}'.format(BucketName, key[0])
                    scene_obj = [cur_folder, m_size, storage_type, restoration_status, collect_time, now_time, now_time,
                                 url, BucketName, key[0], 'v1', 0, 0]
                scene_obj[1] += m_size
            elif re.search(r'original', content.key):
                original_obj = [file_name, m_size, storage_type, restoration_status, collect_time, now_time, now_time,
                                url, BucketName, content.key, 'v1', 0, 0]
                original_list.append(original_obj)
        if scene_obj:
            scene_list.append(scene_obj)
        update_to_original(db, original_list)
        update_to_anonymize(db, anonymize_list)
        update_to_scene(db, scene_list)
    else:
        logger.error("查询obs数据失败%s", resp.errorCode)


def check_storage_class(content):
    storage_class = content.storageClass
    if storage_class == 'STANDARD':
        storage_type = 0
        restoration_status = 0
    elif storage_class == 'WARM':
        storage_type = 1
        restoration_status = 0
    else:
        storage_type = 2
        restore_out = obs_client.getObjectMetadata(BucketName, content.key).body.restore
        if restore_out is None:  # 未恢复
            restoration_status = 1
        elif restore_out.find("true") != -1:  # 恢复中
            restoration_status = 2
        else:  # 已恢复
            restoration_status = 3
    return storage_type, restoration_status


def update_to_original(db, data_list):
    cursor = db.cursor()
    sql = "INSERT ignore INTO data_mgt_originaldata" \
          "(name, size, storage_type, restoration_status, collect_time, " \
          "create_time, update_time, url, bucket_name, object_key, version, download_times, is_delete) " \
          "VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) "
    if data_list:
        try:
            cursor.executemany(sql, data_list)
            db.commit()
        except Exception as e:
            logger.error("同步obs数据失败：%s, %s", repr(e), traceback.format_exc())
            db.rollback()


def update_to_anonymize(db, data_list):
    cursor = db.cursor()
    sql = "INSERT ignore INTO data_mgt_anonymizeddata" \
          "(name, size, storage_type, restoration_status, collect_time, " \
          "create_time, update_time, url, bucket_name, object_key, version, download_times, is_delete, uuid) " \
          "VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) "
    if data_list:
        try:
            cursor.executemany(sql, data_list)
            db.commit()
        except Exception as e:
            logger.error("同步obs数据失败：%s, %s", repr(e), traceback.format_exc())
            db.rollback()


def update_to_scene(db, data_list):
    # db存场景为文件夹级 size为三个小文件之和 用log做
    cursor = db.cursor()
    sql = "INSERT ignore INTO data_mgt_scenedata(name, size, storage_type, restoration_status, collect_time, " \
          "create_time, update_time, url, bucket_name, object_key, version, download_times, is_delete, from_data_id) " \
          "VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 1) "
    if data_list:
        try:
            cursor.executemany(sql, data_list)
            db.commit()
        except Exception as e:
            logger.error("同步obs数据失败：%s, %s", repr(e), traceback.format_exc())
            db.rollback()


if __name__ == '__main__':
    check_obs_new_date(mysql_db)  # 同步obs数据至指定DB中
